package com.soccertgc.core 
{
	
	import com.soccertgc.utils.ClassUtils;

	public class DataObject
	{
		
		// -------------------------------------------------------------------------------
		// CONSTANTS
		// -------------------------------------------------------------------------------
		
		/**
		 * Generic invalid ID used for DataObjects loaded via database record with unique identifiers:
		 * if the object uid is equal to DataObject.INVALID_ID the object has not be loaded
		 */		
		public static const		INVALID_ID:uint			= 0;
		
		// -------------------------------------------------------------------------------
		// FIELDS
		// -------------------------------------------------------------------------------
		
		protected var _loaded:Boolean = false;
		
		// -------------------------------------------------------------------------------
		// CONSTRUCTOR
		// -------------------------------------------------------------------------------
		
		/**
		 * Abstract class that represents an object that can be loaded using a simple
		 * common Actionscript Object. 
		 * 
		 * DO NOT INSTANCE THIS CLASS! Instead inherit from this and use build in utility methods
		 * 
		 */		
		public function DataObject()
		{
			_loaded = false;
		}

		// -------------------------------------------------------------------------------
		// PROPERTIES
		// -------------------------------------------------------------------------------
		
		public function get loaded():Boolean
		{
			return _loaded;
		}
		
		// -------------------------------------------------------------------------------
		// PRIVATE METHODS
		// -------------------------------------------------------------------------------
		
		// Abstract methods
		
		/**
		 * Validates the generic object passed to the load(...) method used to load the DataObject
		 * @param data
		 */		
		protected function validate(data:Object):void
		{
			// throw new Error(ClassUtils.getName(this) + ".validate() must be overridden!");
		}
		
		/**
		 * Adapts the given generic data object into another object compliant with the and fill(...) method
		 * By default the original object is returned
		 * @param data Original object to adapt
		 * @return Adapted object
		 */		
		protected function adapt(data:Object):Object
		{
			return data;
		}
		
		/**
		 * Take the given object and setts the internal data of the DataObject
		 * @param data
		 */		
		protected function fill(data:Object):void
		{
			throw new Error(ClassUtils.getName(this) + ".fill() must be overridden!");
		}
		
		// Base errors throwers
		
		/**
		 * Throws an error to signa a null property value for a required property of the object data used to fill the DataObject
		 */
		protected function throwMethodError(method:String, error:String):void
		{
			throw new Error(ClassUtils.getName(this)  + "." + method + "() failed: " + error);
		}
		
		/**
		 * Throws an error to signa a null property value for a required property of the object data used to fill the DataObject
		 */
		protected function throwLoadPropNullError():void
		{
			throw new Error(ClassUtils.getName(this)  + ".load() failed: object provided should not be null!");
		}
		
		/**
		 * Throws an error to signa a missing property in the generic object used to fill the DataObject
		 * @param field Name of the missing field
		 */
		protected function throwLoadMissingPropError(field:String):void
		{
			throw new Error(ClassUtils.getName(this)  + ".load() failed: object provided doesn't contains '" + field + "' field!");
		}
		
		/**
		 * Throws an error to signa a missing property in the generic object used to fill the DataObject
		 * @param field Name of the missing field
		 */
		protected function throwLoadMissingPathError(path:String, field:String):void
		{
			throw new Error(ClassUtils.getName(this)  + ".load() failed: object provided property " + path + " doesn't contains '" + field + "' field!");
		}
		
		// -------------------------------------------------------------------------------
		// PUBLIC METHODS
		// -------------------------------------------------------------------------------

		/**
		 * 
		 * @param data
		 */		
		public function clear():void
		{
			throw new Error(ClassUtils.getName(this) + ".clear() must be overridden!");
		}
		
		/**
		 * 
		 * @param data
		 */		
		public function load(data:Object):void
		{
			try
			{
				// Validate data to fill the instance!
				validate(data);
				// Adapt the object for filling
				var adapted:Object = adapt(data);
				// Fill data into the instance!
				fill(adapted);
				// Instance has been loaded
				_loaded = true;
			} 
			catch(error:Error) 
			{
				throwMethodError("load", error.message);
			}
		}
		
		/**
		 *  
		 */		
		public function unload():void
		{
			try
			{
				// Clear the data
				clear();
				// Instance has been unloaded
				_loaded = false;
			} 
			catch(error:Error)
			{
				throwMethodError("unload", error.message);
			}
		}
		
		public function forceLoaded():void
		{
			_loaded = true;
		}
		
	}
}